package com.ruoyi.activiti.service.impl;

import com.github.pagehelper.Page;
import com.ruoyi.activiti.domain.ActTaskDTO;
import com.ruoyi.activiti.mapper.SysUserMapper;
import com.ruoyi.activiti.service.ApprovalService;
import com.ruoyi.activiti.util.SecurityUtil;
import com.ruoyi.caigou.api.RemoteBuyBackOrderService;
import com.ruoyi.caigou.api.RemoteBuyBackReqService;
import com.ruoyi.common.core.constant.SecurityConstants;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.common.core.web.page.PageDomain;
import com.ruoyi.common.core.web.page.TableSupport;
import com.ruoyi.common.security.utils.SecurityUtils;
import com.ruoyi.finance.api.RemoteReciveOrderService;
import com.ruoyi.finance.api.RemoteReciveReqService;
import com.ruoyi.system.api.domain.SysUser;
import com.ruoyi.system.api.domain.caigou.BuyBackOrder;
import com.ruoyi.system.api.domain.finance.ReciveOrder;
import com.ruoyi.system.api.domain.finance.ReciveReq;
import com.ruoyi.system.api.dto.ActApprovalDTO;
import com.ruoyi.system.api.model.LoginUser;
import com.ruoyi.xiaoshou.api.RemoteSaleBackRequestService;
import com.ruoyi.xiaoshou.domain.SaleBackRequest;
import lombok.extern.slf4j.Slf4j;
import org.activiti.api.model.shared.model.VariableInstance;
import org.activiti.api.process.model.ProcessInstance;
import org.activiti.api.process.model.builders.ProcessPayloadBuilder;
import org.activiti.api.process.runtime.ProcessRuntime;
import org.activiti.api.runtime.shared.query.Pageable;
import org.activiti.api.task.model.Task;
import org.activiti.api.task.model.builders.TaskPayloadBuilder;
import org.activiti.api.task.runtime.TaskRuntime;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author wangenhao
 * @className ApprovalServiceImpl
 * @description
 * @date 2024-10-30 下午9:17
 **/
@Service
@Slf4j
public class ApprovalServiceImpl implements ApprovalService {

    @Autowired
    private SecurityUtil securityUtil;

    @Autowired
    private ProcessRuntime processRuntime;

    @Autowired
    private RuntimeService runtimeService;

    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private TaskRuntime taskRuntime;

    @Autowired
    private RemoteBuyBackReqService remoteBuyBackReqService;

    @Autowired
    private RepositoryService repositoryService;

    @Autowired
    private RemoteReciveReqService remoteReciveReqService;

    @Autowired
    private RemoteBuyBackOrderService remoteBuyBackOrderService;

    @Autowired
    private RemoteReciveOrderService remoteReciveOrderService;

    @Autowired
    private RemoteSaleBackRequestService remoteSaleBackRequestService;

    @Autowired
    private ProcessEngine processEngine;

    public AjaxResult addApproval(ActApprovalDTO actApprovalDTO) {
//        获取当前登录用户
        LoginUser loginUser = SecurityUtils.getLoginUser();
        SysUser sysUser = loginUser.getSysUser();
        securityUtil.logInAs(sysUser.getUserName());

        //获取可以审核的用户
        String join = StringUtils.join(sysUserMapper.selectUserByDeptId(actApprovalDTO.getDeptId()), ",");
        ProcessInstance processInstance = processRuntime.start(ProcessPayloadBuilder
                .start()
                //根据传入的流程key启动流程
                .withProcessDefinitionKey(actApprovalDTO.getProcessDefinitionKey()) //模板唯一标识
                //获取订单信息作为流程变量
                .withName(actApprovalDTO.getTaskName())
                //获取订单编号作为流程id
                .withBusinessKey(actApprovalDTO.getOrderCode()) //将任务与实际业务表进行绑定
                //设置可以审核的用户
                .withVariable("deptLeader", join)
                //流程实例申请人
                .withVariable("assignee", sysUser.getUserName())
                .build());

        return AjaxResult.success(processInstance.getId());
    }

    public Page<ActTaskDTO> getTaskList(String processDefinitionKey) {
        //条件查询
        PageDomain pageDomain = TableSupport.getPageDomain();
        LoginUser loginUser = SecurityUtils.getLoginUser();
        SysUser sysUser = loginUser.getSysUser();
        securityUtil.logInAs(sysUser.getUserName());

        Page<ActTaskDTO> actTaskDTOPage = new Page<>();

        // 通过 runtimeService 查询指定流程定义的所有流程实例 ID
        List<String> processInstanceIds = runtimeService.createProcessInstanceQuery()
                .processDefinitionKey(processDefinitionKey) // 根据流程定义 Key 过滤
                .list()
                .stream()
                .map(org.activiti.engine.runtime.ProcessInstance::getId)
                .collect(Collectors.toList());

        if (processInstanceIds.isEmpty()) {
            return actTaskDTOPage; // 如果没有找到流程实例，则直接返回空分页对象
        }

        // 使用 taskRuntime 查询待办任务，并过滤符合流程实例 ID 列表的任务
        org.activiti.api.runtime.shared.query.Page<Task> taskPage = taskRuntime.tasks(
                Pageable.of((pageDomain.getPageNum() - 1) * pageDomain.getPageSize(), pageDomain.getPageSize()),
                TaskPayloadBuilder.tasks()
                        .withAssignee(sysUser.getUserName()) // 按用户筛选
                        .build()
        );

        // 获取查询到的任务列表，并按流程实例 ID 进行过滤
        List<Task> tasks = taskPage.getContent().stream()
                .filter(task -> processInstanceIds.contains(task.getProcessInstanceId()))
                .collect(Collectors.toList());

        int totalItems = taskPage.getTotalItems();
        actTaskDTOPage.setTotal(totalItems);
        if (totalItems != 0) {
            Set<String> processInstanceIdIds = tasks.parallelStream().map(t -> t.getProcessInstanceId()).collect(Collectors.toSet());
            List<org.activiti.engine.runtime.ProcessInstance> processInstanceList = runtimeService.createProcessInstanceQuery().processInstanceIds(processInstanceIdIds).list();
            List<ActTaskDTO> actTaskDTOS = tasks.stream()
                    .map(t -> new ActTaskDTO(t, processInstanceList.parallelStream().filter(pi -> t.getProcessInstanceId().equals(pi.getId())).findAny().get()))
                    .collect(Collectors.toList());
            actTaskDTOPage.addAll(actTaskDTOS);

        }
        /*
          获取流程实例中的变量 并返回 这里取出变量中附件的地址
         */
        Page<ActTaskDTO> listAfter = new Page<ActTaskDTO>();
        for (ActTaskDTO actTaskDTO : actTaskDTOPage) {
            List<VariableInstance> variableInstanceList = processRuntime.variables(ProcessPayloadBuilder
                    .variables()
                    .withProcessInstanceId(actTaskDTO.getInstanceId())
                    .build()
            );
            for (VariableInstance vi : variableInstanceList) {
                if ("assignee".equals(vi.getName())) {        //获取申请人
                    actTaskDTO.setAssignee(vi.getValue());
                }
            }
            listAfter.add(actTaskDTO);
        }
        return listAfter;
    }


    public AjaxResult formDataShow(String taskID) {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        SysUser sysUser = loginUser.getSysUser();
        securityUtil.logInAs(sysUser.getUserName());

        // 获取 Task 信息
        Task task = taskRuntime.task(taskID);

        // 获取 ProcessInstanceId
        String processInstanceId = task.getProcessInstanceId();

        // 通过 ProcessInstance 获取 BusinessKey
        String businessKey = null;
        if (processInstanceId != null) {
            ProcessInstance processInstance = processRuntime.processInstance(processInstanceId);
            businessKey = processInstance.getBusinessKey();  // 获取到 BusinessKey
        }

        log.info("formDataShow BusinessKey:{} Task: {}", businessKey, task);

        // 使用 BusinessKey 进行后续操作
        return remoteBuyBackReqService.getInfoByCode(businessKey);
    }

    @Override
    public AjaxResult saleHandelApproval(String processInstanceId) {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        SysUser sysUser = loginUser.getSysUser();
        securityUtil.logInAs(sysUser.getUserName());
        org.activiti.engine.task.Task task = processEngine.getTaskService().createTaskQuery().processInstanceId(processInstanceId).active().singleResult();
        task.getId();
        ActApprovalDTO actApprovalDTO = new ActApprovalDTO();
        actApprovalDTO.setTaskId(task.getId());
        actApprovalDTO.setApprovalResult(1);
        actApprovalDTO.setApprovalOption("系统自动审核通过");
        return this.handelApproval(actApprovalDTO);
    }

    public AjaxResult handelApproval(ActApprovalDTO actApprovalDTO) {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        SysUser sysUser = loginUser.getSysUser();
        securityUtil.logInAs(sysUser.getUserName());

        Task task = taskRuntime.task(actApprovalDTO.getTaskId());
//        org.activiti.engine.runtime.ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult();
        // 如果任务未分配，则先签收
        if (task.getAssignee() == null) {
            taskRuntime.claim(TaskPayloadBuilder.claim().withTaskId(task.getId()).build());
        }
        // 完成任务
        taskRuntime.complete(TaskPayloadBuilder.complete().withTaskId(actApprovalDTO.getTaskId())
                //审核结果和意见
                .withVariable("approvalResult", actApprovalDTO.getApprovalResult())
                .withVariable("approvalOption", actApprovalDTO.getApprovalOption())
                .build());

        return AjaxResult.success();
    }


    public AjaxResult buyBackOrderShow(String taskId) {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        SysUser sysUser = loginUser.getSysUser();
        securityUtil.logInAs(sysUser.getUserName());

        // 获取 Task 信息
        Task task = taskRuntime.task(taskId);

        // 获取 ProcessInstanceId
        String processInstanceId = task.getProcessInstanceId();

        // 通过 ProcessInstance 获取 BusinessKey
        String businessKey = null;
        if (processInstanceId != null) {
            ProcessInstance processInstance = processRuntime.processInstance(processInstanceId);
            businessKey = processInstance.getBusinessKey();  // 获取到 BusinessKey
        }

        log.info("buyBackOrderShow BusinessKey:{} Task: {}", businessKey, task);

        // 使用 BusinessKey 进行后续操作
        R<BuyBackOrder> infoByBuyBackOrderCode = remoteBuyBackOrderService.getInfoByBuyBackOrderCode(businessKey);
        return AjaxResult.success(infoByBuyBackOrderCode.getData());
    }

    /**
     * @return com.ruoyi.common.core.web.domain.AjaxResult
     * @description 获取财务应收单详情
     * @date 2024/11/10 下午11:12
     * @Param taskId:
     **/
    public AjaxResult reciveReqShow(String taskId) {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        SysUser sysUser = loginUser.getSysUser();
        securityUtil.logInAs(sysUser.getUserName());

        // 获取 Task 信息
        Task task = taskRuntime.task(taskId);

        // 获取 ProcessInstanceId
        String processInstanceId = task.getProcessInstanceId();

        // 通过 ProcessInstance 获取 BusinessKey
        String businessKey = null;
        if (processInstanceId != null) {
            ProcessInstance processInstance = processRuntime.processInstance(processInstanceId);
            businessKey = processInstance.getBusinessKey();  // 获取到 BusinessKey
        }

        log.info("reciveReqShow BusinessKey:{} Task: {}", businessKey, task);

        // 使用 BusinessKey 进行后续操作
        R<ReciveReq> reciveReqInfo = remoteReciveReqService.getReciveReqByOrderCode(businessKey);
        return AjaxResult.success(reciveReqInfo.getData());
    }

    /**
     * @return com.ruoyi.common.core.web.domain.AjaxResult
     * @description 获取财务收款单详情
     * @date 2024/11/11 下午10:29
     * @Param taskId:
     **/
    public AjaxResult reciveOrderShow(String taskId) {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        SysUser sysUser = loginUser.getSysUser();
        securityUtil.logInAs(sysUser.getUserName());

        // 获取 Task 信息
        Task task = taskRuntime.task(taskId);

        // 获取 ProcessInstanceId
        String processInstanceId = task.getProcessInstanceId();

        // 通过 ProcessInstance 获取 BusinessKey
        String businessKey = null;
        if (processInstanceId != null) {
            ProcessInstance processInstance = processRuntime.processInstance(processInstanceId);
            businessKey = processInstance.getBusinessKey();  // 获取到 BusinessKey
        }

        log.info("reciveReqShow BusinessKey:{} Task: {}", businessKey, task);

        // 使用 BusinessKey 进行后续操作
        R<ReciveOrder> reciveOrderR = remoteReciveOrderService.getReciveOrderByOrderCode(businessKey);
        return AjaxResult.success(reciveOrderR.getData());
    }
    public AjaxResult saleBackReqShow(String taskId) {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        SysUser sysUser = loginUser.getSysUser();
        securityUtil.logInAs(sysUser.getUserName());

        // 获取 Task 信息
        Task task = taskRuntime.task(taskId);

        // 获取 ProcessInstanceId
        String processInstanceId = task.getProcessInstanceId();

        // 通过 ProcessInstance 获取 BusinessKey
        String businessKey = null;
        if (processInstanceId != null) {
            ProcessInstance processInstance = processRuntime.processInstance(processInstanceId);
            businessKey = processInstance.getBusinessKey();  // 获取到 BusinessKey
        }

        log.info("saleBackReqShow BusinessKey:{} Task: {}", businessKey, task);

        // 使用 BusinessKey 进行后续操作
        R<SaleBackRequest> reciveOrderR = remoteSaleBackRequestService.getSaleBackRequestByCode(businessKey, SecurityConstants.INNER);
        return AjaxResult.success(reciveOrderR.getData());
    }
}
